//---------------------------------------------------------------------------- 
//Initialisation


var stateIsLoaded = false;

var isTitleEditing = false;
var currentTitle = null;

var fieldsToBeEdited = new Array();
var lastAddedOptionId = null;

/**
 * If we edit one or several option captions, we keep their original value, in
 * order to see on a state change if someone else has changed the caption or not
 * (while we were editing).
 */
var currentEditedOptionsOriginalCaptions = new Object();

var debug = false;

// --- Begin of code ---

function init() {
	if (wave && wave.isInWaveContainer()) {
		wave.setStateCallback(waveStateHasChanged);

		// we need this because if the table width shrinks, the gadget
		// might have a higher height, and vice versa.
		$(window).resize(function() {
			gadgets.window.adjustHeight();
		});
	}
}

function initAfterStateIsloaded() {
	if (isWaveHost()) {
		// $('#add_option_tbody').show();
	}
	trackUsage();
}

function trackUsage() {
	// Google analytics - track gadget use:
	// We track how many polls were created using this gadget,
	// and how often the gadget was displayed by the host and by the other users
	// More information:
	// http://code.google.com/p/flexibleyesnomaybegadget/wiki/GoogleAnalytics
	var ga = new _IG_GA("UA-17061647-4");

	if (isWaveHost()) {
		var state = wave.getState();
		var creationAlreadyTracked = state.get('creationAlreadyTracked', '0');
		if (creationAlreadyTracked == '0') {
			ga.reportEvent("Multiple YNM Gadget", "Creation");
			state.submitValue('creationAlreadyTracked', '1');
		}
		ga.reportPageview('/view/MultipleYNMGadget/Host');
	} else {
		ga.reportPageview('/view/MultipleYNMGadget/Viewer');
	}

}

// ----------------------------------------------------------------------------
// State-Update


function waveStateHasChanged() {
	if (!stateIsLoaded) {
		stateIsLoaded = true;
		initAfterStateIsloaded();
	}

	try {
		setTitleFromState();

		createModelFromState();
		synchroniseViewWithModel();

		synchroniseVisibleOptionRowCaptions();

		checkToggleLock();
	} catch (err) {
		if (err != 'Removed old votes') {
			throw err;
		}
	} finally {
		gadgets.window.adjustHeight();
	}
}

function toggleLock() {
	if (!isWaveHost()) {
		return;
	}

	var state = wave.getState();
	var isLocked = state.get('locked', 0);
	state.submitValue('locked', (1 - isLocked));
}

function checkToggleLock() {
	var state = wave.getState();
	var isLocked = (state.get('locked', 0) == 1);

	if (isLocked) {
		if (!isWaveHost()) {
			$("[id^='cmd_']").hide();
			$("[id^='caption_']").removeClass('optioncanbeeditedcaption');
			$('#add_option_tbody').hide();
			$('#reset_option_tbody').hide();
			$('#title').css('');
			$('#lock_this_gadget').hide();
		} else {
			$('#locklink').html('Unlock');
			$('#lockhint').html(
					'(Currently, only you can add/remove/edit options)');
		}
	} else {
		if (!isWaveHost()) {
			$("[id^='cmd_']").show();
			$("[id^='caption_']").addClass('optioncanbeeditedcaption');
			$('#add_option_tbody').show();
			$('#reset_option_tbody').show();
			$('#title').css('cursor:pointer;');
			$('#lock_this_gadget').hide();
		} else {
			$('#locklink').html('Lock');
			$('#lockhint').html(
					'(Currently, anyone can add/remove/edit options)');
		}
	}
}

function setTitleFromState() {
	var state = wave.getState();
	var title = state.get('title', null);

	var titleEditboxSelector = getIdSelector('title_edit_box');

	/*
	 * If the title is empty, always show edit box.
	 * 
	 * If the edit box is present, but was only displayed because the title was
	 * set empty by someone else, remove the edit box after someone edited the
	 * title and the current user did not make any changes inside the edit box.
	 * 
	 * Otherwise, simply update title.
	 */
	var titleWasChanged =
			((trim(currentTitle) != trim(title)) && (title != null));
	var titleIsEmpty = (trim(title) == '' || title == null);

	if (titleIsEmpty && !isTitleEditing) {
		editTitle();
	} else if (isTitleEditing && !titleWasChanged) {
		// do nothing.
		// this might happen if we edit the title, and in between,
		// the state is updated because someone voted or edited an option
	} else if (isTitleEditing && (trim(title) == '')) {
		// clear title, but keep edit box
		var titleEditboxSelector = getIdSelector('title_edit_box');
		$(titleEditboxSelector).val(title);
		currentTitle = title;
	} else {
		// update title.
		// if we are editing, then someone else was quicker, display their
		// title then.
		var titleSelector = getIdSelector('title');
		$(titleSelector).html(renderTitleSpan(title));
		isTitleEditing = false;
		currentTitle = null;
	}
}

function synchroniseVisibleOptionRowCaptions() {
	var state = wave.getState();
	var state_keys = state.getKeys();

	var isLocked = (state.get('locked', 0) == 1);
	var hasEditRights = (isWaveHost() || !isLocked);

	for ( var key in model.options) {
		var currentCaptionTrimmed = trim(state.get(key, ''));
		processCaption(key, currentCaptionTrimmed, hasEditRights);
	}

	showOrHideOptionCommandLines(hasEditRights);
}

function processCaption(key, currentCaptionTrimmed, hasEditRights) {
	// init
	var editField = document.getElementById("captionedit_" + key);
	var editFieldIsVisible = (editField != null);

	var captionIsEmpty = (currentCaptionTrimmed == '');

	var currentEditedCaptionTrimmed = null;
	if (editFieldIsVisible) {
		currentEditedCaptionTrimmed = trim(editField.value);
	}
	var currentEditedCaptionIsEmpty = (currentEditedCaptionTrimmed == '');

	var someoneElseWasQuicker =
			(currentEditedOptionsOriginalCaptions[key] != currentCaptionTrimmed);
	var weHaveNotChangedAnythingYet =
			(currentEditedOptionsOriginalCaptions[key] == currentEditedCaptionTrimmed);

	var captionFieldShouldBeHidden =
			someoneElseWasQuicker
					&& (weHaveNotChangedAnythingYet || currentEditedCaptionIsEmpty);
	
	var captionShouldBeEdited = captionIsEmpty || checkIfCaptionShouldBeEdited(key);

	// Now find out what to do
	var _showCaptionEditField = 
			(!editFieldIsVisible && hasEditRights && captionShouldBeEdited);

	var _keepCaptionEditField =
			(editFieldIsVisible && hasEditRights && (captionIsEmpty || !captionFieldShouldBeHidden));

	var _hideCaptionEditField =
			(editFieldIsVisible && (!hasEditRights || !_keepCaptionEditField));

	var onlyReplaceCaption =
			!(_showCaptionEditField || _keepCaptionEditField || _hideCaptionEditField);

	// and apply
	if (_showCaptionEditField) {
		showCaptionEditField(key);
	} else if (_hideCaptionEditField) {
		hideCaptionEditField(key, currentCaptionTrimmed);
	} else if (onlyReplaceCaption) {
		replaceCaptionByNew(key, currentCaptionTrimmed);
	}
}


function replaceCaptionByNew(key, caption) {
	var spanSelector = getIdSelector('caption_' + key);
	$(spanSelector).html(escapeHtml(caption));
}



function checkIfCaptionShouldBeEdited(optionId) {
	for ( var idx in fieldsToBeEdited) {
		var currOptionId = fieldsToBeEdited[idx];
		if (optionId == currOptionId) {
			fieldsToBeEdited.splice(idx, 1);
			return true;
		}
	}
	return false;
}

function showOrHideOptionCommandLines(hasEditRights) {
	var commandLinesSelector = "span[id^='cmd_']";
	if (hasEditRights) {
		$(commandLinesSelector).show();
	} else {
		$(commandLinesSelector).hide();
	}
}

// ----------------------------------------------------------------------------
// Event-Handler

function addOptionRow() {
	var state = wave.getState();

	var isLocked = (state.get('locked', 0) == 1);
	if (!isWaveHost() && isLocked) {
		return;
	}

	var caption = '';
	var key = 'option' + '_' + getUniqueId();

	lastAddedOptionId = key;

	state.submitValue(key, caption);
}

function checkVote(optionId, answer) {
	var participantId = getWaveViewerId();
	var existingVote = model.getVoteFor(optionId, participantId);

	if (existingVote == answer) {
		var voteToBeRemovedId = createVoteId(optionId, participantId);
		removeVote(voteToBeRemovedId, optionId, answer);
	} else {
		// add or toggle
		addVote(optionId, answer);
	}
}

function addVote(optionId, answer) {
	var participantId = getWaveViewerId();
	var state = wave.getState();
	var key = createVoteId(optionId, participantId);
	state.submitValue(key, answer);

	gadgets.window.adjustHeight();
}

function createVoteId(optionId, participantId) {
	var participantId_encoded = encodeURIComponent(participantId);

	var id = 'vote' + '::' + optionId + '::' + participantId_encoded;

	return id;
}

function editTitle() {
	var state = wave.getState();

	var isLocked = (state.get('locked', 0) == 1);
	if (!isWaveHost() && isLocked) {
		return;
	}

	currentTitle = state.get('title', 'Title');
	var handler = 'saveTitle();';
	var editBoxId = 'title_edit_box';

	var titleEditForm = renderSimpleEditForm(handler, editBoxId, currentTitle);

	var titleSelector = getIdSelector('title');
	$(titleSelector).html(titleEditForm);

	focusAndSelectEditFieldWithId(editBoxId);

	isTitleEditing = true;
	gadgets.window.adjustHeight();
}

function saveTitle() {
	var state = wave.getState();
	var title;

	var isLocked = (state.get('locked', 0) == 1);
	if (!isWaveHost() && isLocked) {
		title = state.get('title', 'title');
		removeTitleInputAndReplaceByTitle(title);
		return;
	}

	var titleEditboxSelector = getIdSelector('title_edit_box');
	title = $(titleEditboxSelector).val();

	if (trim(title) != '') {
		removeTitleInputAndReplaceByTitle(title);
	}

	state.submitValue('title', title);
}

function removeTitleInputAndReplaceByTitle(title) {
	var titleSelector = getIdSelector('title');
	$(titleSelector).html(renderTitleSpan(title));
	isTitleEditing = false;
	currentTitle = null;
	gadgets.window.adjustHeight();
}

function editCaption(optionId) {
	var state = wave.getState();
	var isLocked = (state.get('locked', 0) == 1);
	if (!isWaveHost() && isLocked) {
		return;
	}

	showCaptionEditField(optionId);
	gadgets.window.adjustHeight();
}

function saveCaption(optionId) {
	var state = wave.getState();

	var isLocked = (state.get('locked', 0) == 1);
	if (!isWaveHost() && isLocked) {
		var caption = state.get(optionId, '');
		hideCaptionEditField(optionId, caption);
		synchroniseVisibleOptionRowCaptions();
		gadgets.window.adjustHeight();
		return;
	}

	var editFieldSelector = getIdSelector("captionedit_" + optionId);
	
	var newCaptionTrimmed = trim($(editFieldSelector).val());
	var oldCaption = currentEditedOptionsOriginalCaptions[optionId];
	
	var hasChanged = (newCaptionTrimmed != oldCaption);
	
	if (newCaptionTrimmed != '') {
		hideCaptionEditField(optionId, newCaptionTrimmed);
		gadgets.window.adjustHeight();
	}
	
	if (hasChanged){
		state.submitValue(optionId, newCaptionTrimmed);
		focusNextEditFieldIfAny(optionId);
	}else{
		synchroniseVisibleOptionRowCaptions();
	}
	
}

function focusNextEditFieldIfAny(optionId) {
	var sortedIds = new Array();

	for ( var currentId in currentEditedOptionsOriginalCaptions) {
		sortedIds.push(currentId);
	}

	sortedIds.sort();

	var length = sortedIds.length;
	var selectAny = (length > 0 && sortedIds[length - 1] <= optionId);

	for ( var idx in sortedIds) {
		var currId = sortedIds[idx];
		if ((currId < optionId) && !selectAny) {
			continue;
		}

		var inputBox = document.getElementById("captionedit_" + currId);
		var weHaveInputBoxForCaption = (inputBox != null);

		if (weHaveInputBoxForCaption) {
			inputBox.focus();
			break;
		}
	}

}

function copyOption(optionId) {
	var state = wave.getState();

	var isLocked = (state.get('locked', 0) == 1);
	if (!isWaveHost() && isLocked) {
		return;
	}

	if (!model.options[optionId]) {
		// if this was deleted meanwhile...
		return;
	}

	var children = getChildenSorted(optionId);

	var newKey;
	if (children.length == 0) {
		newKey = optionId + '0' + getUniqueId();
	} else {
		firstChild = children[0];
		var prefixLength = optionId.length;
		var childPostFix = firstChild.substr(prefixLength);
		newKey = optionId + '0' + childPostFix;
	}

	var caption = model.options[optionId].caption;

	lastAddedOptionId = newKey;
	fieldsToBeEdited.push(newKey);

	state.submitValue(newKey, caption);
}

function getChildenSorted(optionId) {
	var childrenSorted = new Array();

	var selector = "[id^='" + optionId + "0']";
	$(selector).each(function(idx, domElement) {
		childrenSorted.push($(domElement).attr('id'));
	});

	childrenSorted.sort();

	return childrenSorted;
}
function removeOption(optionId) {
	var state = wave.getState();

	var isLocked = (state.get('locked', 0) == 1);
	if (!isWaveHost() && isLocked) {
		return;
	}

	var state = wave.getState();
	state.submitValue(optionId, null);
}

function removeVote(voteId, optionId, answer) {
	var state = wave.getState();
	state.submitValue(voteId, null);

	if (!debug) {
		removeVoteSpanFromDOM(voteId + '::' + answer);
	}

}

function clearAllVotes(){
	
	var state = wave.getState();

	var isLocked = (state.get('locked', 0) == 1);
	if (!isWaveHost() && isLocked) {
		return;
	}

    var state_keys = state.getKeys();
	for ( var idx in state_keys) {
		var key = state_keys[idx];
		var isVoteKey = (voteKeyPrefix == key.substr(0, voteKeyPrefixLength));
		if (isVoteKey){
			state.submitValue(key, null);
		}
	}	    
}
